#include "widget.h"
#include "ui_widget.h"

#include <QFile>
#include <QFileDialog>


Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //虽然上面的代码进行widget和ui的关联，但是如果发生窗体大小变化，此控件内部的布局不会变化
    //通过下面这行代码进行显示说明，让窗口变化时，布局及其子控件随之调整
    this->setLayout(ui->verticalLayout);
    //右下角组件跟页面变化
    ui->widgetBottom->setLayout(ui->horizontalLayout_2);


    //信号与槽
    //第二种方式：QObject::connect(sender,SIGNAL(signal()),receiver,SLOT(slot()));
    QObject::connect(ui->btnOpen,SIGNAL(clicked()),this,SLOT(onBtnOpenClicked()));

    //第三种方式：lambda表达式
    //QObject::connect(sender,&Sender::signal,[=](){/*lambda body*/});
    QObject::connect(ui->btnSave,&QPushButton::clicked,[=](){
        std::cout<<"UI BTN SAVE CLICKED——method3：lambda"<<std::endl;
        /*       //QFile写入文件的五步
        //1.选中文件
        QFile file("../../../save.txt");
        //2.打开文件
        file.open(QIODeviceBase::WriteOnly|QIODeviceBase::Text);
        //3.写入文件
        char* textToWrite = "here are some words i want to say to you";
        file.write(textToWrite);
        //4.关闭文件
        file.close();
*//*
        //QTextFile写入文件的几步：
        //1.选中文件
        QFile file("../../../save.txt");
        //2.打开文件
        file.open(QIODeviceBase::Append|QIODeviceBase::Text);//append追加方式写入
        //3.实例化QTextStream对象，并设置显示的编码
        QTextStream out(&file);
        out.setEncoding(QStringConverter::Utf8);
        //4.开始向文件内输出内容
        out<<Qt::endl<<"I append some words in this file.";
        //5.关闭文件
        file.close();
        */
        //使用QFileDialog类，调出文件浏览器进行文件保存操作
        QString fileName = QFileDialog::getSaveFileName(this,tr("Open File"),"/home/Untitled.txt",tr("Images(*.png *.xpm *.jpg *.txt)"));
        //使用QTextStream进行读取
        //1.选中文件
        //QFile file;
        file.setFileName(fileName);
        //2.打开文件
        file.open(QIODeviceBase::WriteOnly|QIODevice::Text);//bool类型返回值，可以进行是否成功打开的验证，此处没做
        //设置窗口名称
        this->setWindowTitle(fileName + "——NoteBook@Honevid");

        //3.实例化QTextStream对象，并设置显示的编码
        QTextStream out(&file);
        out.setEncoding(encodingMap[ui->comboBox->currentText()]);
        //4.写入文本，设置接收值的容器
        out<<ui->textEdit->toPlainText();
        //6.关闭文件
        //file.close();
    });

    //第四种方法：QT5新特性
    QObject::connect(ui->btnClear,&QPushButton::clicked,this,&Widget::onBtnClearClicked);

    //绑定combo box事件
    connect(ui->comboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(onCurrentIndexChanged(int)));

    //将自定义信号与自定义槽绑定
    connect(this,SIGNAL(mySignal()),this,SLOT(mySlot()));//Widget是QObject的孙类，因此可以识别connect
    emit mySignal();
    //将自定义信号与自定义槽绑定——带参数的
    connect(this,SIGNAL(mySignalWithParams(int)),this,SLOT(mySlotWithParams(int)));//Widget是QObject的孙类，因此可以识别connect
    emit mySignalWithParams(100);

    connect(ui->textEdit,SIGNAL(cursorPositionChanged()),this,SLOT(onCursorPositionChanged()));
}

Widget::~Widget()
{
    delete ui;
}


//第一种方式，使用uiDesigner
void Widget::on_btnClose_clicked()
{
    std::cout<<"UI BTN CLOSE CLICKED——method1：uiDesigner"<<std::endl;
    //
    if(file.isOpen()){
        file.close();
        ui->textEdit->clear();
        this->setWindowTitle("NoteBook@Honevid");
    }
}
//第二种方式：使用connect
void Widget::onBtnOpenClicked()
{
    std::cout<<"UI BTN OPEN CLICKED——method2：connect by hand"<<std::endl;
    //使用QFileDialog类，调出文件浏览器进行文件访问
    QString fileName = QFileDialog::getOpenFileName(this,tr("Open File"),"/home",tr("Images(*.png *.xpm *.jpg *.txt)"));

    /*    //使用file.read读取文件的五步
    //1.选中文件
    //1.1 打开方式一：直接传入文件名到file里面
    //QFile file("../../../test.txt");
    //1.2 打开方式二：file不传文件名，仅实例化对象，在file.setFileName("file.txt")中设置文件地址
    QFile file;
    file.setFileName("../../../test.txt");

    //2.打开文件
    if(!file.open(QIODeviceBase::ReadWrite|QIODeviceBase::Text)){
        qDebug()<<"file can not be opened!";
    }
    //3.读取文件
    char container[100]={'\0'};
    if(file.read(container,100)==-1){
        return;
    }

    //4.输出文件
    qDebug()<<container;

    //5.关闭文件
    file.close();
*/

    //使用QTextStream进行读取
    //1.选中文件
    ui->textEdit->clear();//选中文件前先清空
    //QFile file;
    file.setFileName(fileName);
    //2.打开文件
    file.open(QIODeviceBase::ReadOnly|QIODevice::Text);//bool类型返回值，可以进行是否成功打开的验证，此处没做
    this->setWindowTitle(fileName+"*——NoteBook@Honevid");
    //3.实例化QTextStream对象，并设置显示的编码
    QTextStream in(&file);
    // if(encodingMap[ui->comboBox->currentText()]==QStringConverter::Utf8){//判断map对应是否正确
    //     qDebug()<<ui->comboBox->currentText();
    // }
    qDebug()<<ui->comboBox->currentText();//打印当前编码值
    in.setEncoding(encodingMap[ui->comboBox->currentText()]);
    // //4.读取文本，设置接收值的容器
    // //4.1读取全部文件
    // QString container = in.read(file.size());
    // ui->textEdit->setText(container);
    //4.2按行读取
    while(!in.atEnd()){//atEnd()==>返回值是bool，当到达尾部返回true
        QString container = in.readLine();
        // //5.输出文件
        // qDebug()<<container;
        // qDebug()<<"=========";
        ui->textEdit->append(container);
    }

    //6.关闭文件
    //file.close();


}
//第四种方式：使用QT5新特性
void Widget::onBtnClearClicked()
{
    std::cout<<"UI BTN CLEAR CLICKED——method4：new QT5"<<std::endl;

    //打开多个文件
    //1.实例化Qfiledialog
    QFileDialog qFileDialog;
    //2.设置模式
    qFileDialog.setFileMode(QFileDialog::ExistingFiles);
    //3.设置文件过滤器（可选）
    qFileDialog.setNameFilter("*.txt");//只显示txt
    //4.运行窗口
    qFileDialog.exec();
    //5.获取文件的列表
    QStringList qstrings = qFileDialog.selectedFiles();
    //使用迭代器进行输出展示
    for(QString str:qstrings){
        qDebug()<<str;
    }

}

void Widget::onCurrentIndexChanged(int index)
{
    qDebug()<<index;//索引从0开始
    qDebug()<<ui->comboBox->currentText();

    //切换编码时，首先清空当前的文本框
    ui->textEdit->clear();
    if(file.isOpen()){//仅在文件打开情况下进行重新读取的动作
        //3.实例化QTextStream对象，并设置显示的编码
        QTextStream in(&file);
        qDebug()<<ui->comboBox->currentText();//打印当前编码值
        in.setEncoding(encodingMap[ui->comboBox->currentText()]);
        //in.seek(0);        //光标回到文件头部
        file.seek(0);       //与in.seek(0);功能一样
        while(!in.atEnd()){//atEnd()==>返回值是bool，当到达尾部返回true
            QString container = in.readLine();
            ui->textEdit->append(container);
        }
    }
}

void Widget::onCursorPositionChanged()
{
    //ui->textPosition->setText("");
    QTextCursor cursor = ui->textEdit->textCursor();
    //qDebug()<<cursor.columnNumber()<<cursor.blockNumber();//行号是blocknumber，列号是columnnumber

    const QString blockNumber = QString::number(cursor.blockNumber()+1);
    const QString columnNumber = QString::number(cursor.columnNumber()+1);
    const QString labelMessage = blockNumber+"行，"+columnNumber+"列";

    ui->textPosition->setText(labelMessage);
}

//自定义的无参数信号执行槽
void Widget::mySlot()
{
    std::cout<<"my slot is running "<<std::endl;
}

//自定义的有参数信号执行槽
void Widget::mySlotWithParams(int value)
{
    std::cout<<"my slot is running for"<<value<<std::endl;
    qDebug()<<"my slot is running for"<<value;//使用QDebug进行输出
}
